<template>
	<div
		class="container3d"
		ref="elContainer"
		v-loading="loading"
		element-loading-text="正在处理..."
		element-loading-background="rgba(0, 0, 0, 0.8)"
		@mousedown.prevent="onSelectView"
	>
		<div
			:id="ViewportId.AXIAL"
			class="axialparent"
			:style="axialStyle"
			v-show="showAxial"
			@dblclick="onDbClick"
		>
			<div ref="elAxial" class="sliceview" @contextmenu.prevent>
				<h4 class="desc">{{ axialText.desc }}</h4>
				<span class="text_studyinfo">{{ studyInfo }}</span>
				<span class="text_wwwc">{{ axialText.wwwc }}</span>
				<span class="text_slice">{{ axialText.slice }}</span>
				<span class="orient_top" v-show="showOrientText">{{
					axialText.orient.top
				}}</span>
				<span class="orient_bottom" v-show="showOrientText">{{
					axialText.orient.bottom
				}}</span>
				<span class="orient_left" v-show="showOrientText">{{
					axialText.orient.left
				}}</span>
				<span class="orient_right" v-show="showOrientText">{{
					axialText.orient.right
				}}</span>
			</div>
		</div>
		<div
			:id="ViewportId.VOLUME"
			class="vrcprparent"
			:style="vrStyle"
			v-show="showVR"
			@dblclick="onDbClick"
		>
			<div ref="elVR" class="sliceview" @contextmenu.prevent>
				<h4 class="desc">VR</h4>
				<span class="text_studyinfo">{{ studyInfo }}</span>
				<div class="vr-camera">
					<IconButton
						icon="icon-A"
						color="#DCDCDC"
						hoverColor="#A0A0A0"
						size="30px"
						@click="setCameraPos('A')"
					/>
					<IconButton
						icon="icon-P"
						color="#DCDCDC"
						hoverColor="#A0A0A0"
						size="30px"
						@click="setCameraPos('P')"
					/>
					<IconButton
						icon="icon-L"
						color="#DCDCDC"
						hoverColor="#A0A0A0"
						size="30px"
						@click="setCameraPos('L')"
					/>
					<IconButton
						icon="icon-R"
						color="#DCDCDC"
						hoverColor="#A0A0A0"
						size="30px"
						@click="setCameraPos('R')"
					/>
					<IconButton
						icon="icon-S"
						color="#DCDCDC"
						hoverColor="#A0A0A0"
						size="30px"
						@click="setCameraPos('S')"
					/>
					<IconButton
						icon="icon-I"
						color="#DCDCDC"
						hoverColor="#A0A0A0"
						size="30px"
						@click="setCameraPos('I')"
					/>
				</div>
			</div>
		</div>
		<div
			:id="ViewportId.SAGITTAL"
			class="sagittalparent"
			:style="sagittalStyle"
			v-show="showSagittal"
			@dblclick="onDbClick"
		>
			<div ref="elSagittal" class="sliceview" @contextmenu.prevent>
				<h4 class="desc">{{ sagittalText.desc }}</h4>
				<span class="text_studyinfo">{{ studyInfo }}</span>
				<span class="text_wwwc">{{ sagittalText.wwwc }}</span>
				<span class="text_slice">{{ sagittalText.slice }}</span>
				<span class="orient_top" v-show="showOrientText">{{
					sagittalText.orient.top
				}}</span>
				<span class="orient_bottom" v-show="showOrientText">{{
					sagittalText.orient.bottom
				}}</span>
				<span class="orient_left" v-show="showOrientText">{{
					sagittalText.orient.left
				}}</span>
				<span class="orient_right" v-show="showOrientText">{{
					sagittalText.orient.right
				}}</span>
			</div>
		</div>
		<div
			:id="ViewportId.CORONAL"
			class="coronalparent"
			:style="coronalStyle"
			v-show="showCoronal"
			@dblclick="onDbClick"
		>
			<div ref="elCoronal" class="sliceview" @contextmenu.prevent>
				<h4 class="desc">{{ coronalText.desc }}</h4>
				<span class="text_studyinfo">{{ studyInfo }}</span>
				<span class="text_wwwc">{{ coronalText.wwwc }}</span>
				<span class="text_slice">{{ coronalText.slice }}</span>
				<span class="orient_top" v-show="showOrientText">{{
					coronalText.orient.top
				}}</span>
				<span class="orient_bottom" v-show="showOrientText">{{
					coronalText.orient.bottom
				}}</span>
				<span class="orient_left" v-show="showOrientText">{{
					coronalText.orient.left
				}}</span>
				<span class="orient_right" v-show="showOrientText">{{
					coronalText.orient.right
				}}</span>
			</div>
		</div>
	</div>
</template>

<script setup name="DisplayerArea3d">
import {
	ref,
	onMounted,
	onBeforeUnmount,
	computed,
	reactive,
	watch,
	onUnmounted
} from "vue";
import MPR from "../cornerstone3D/mprvr.js";
import { ViewportId, getDicomInfo } from "../cornerstone3D/mprvr.js";
import { useAppStore } from "../stores/appStore.js";
import { storeToRefs } from "pinia";
import IconButton from "./IconButton.vue";

const appStore = useAppStore();
const { currentDisplayer, blendMode } = storeToRefs(appStore);

let theMPR = null;
const loading = ref(false);
const layout = reactive({
	type: "layoutmprvr",
	viewIds: [],
	maxViewId: null
});

let resizeObserver = null;

const studyInfo = ref("");
const defWL = ref(40);
const defWW = ref(400);
const showAxial = ref(true);
const showSagittal = ref(true);
const showCoronal = ref(true);
const showVR = ref(true);
const currentViewportId = ref("");
// const measureType = ref("measure-none");
const showOrientText = ref(true);

const elContainer = ref(null);
const elAxial = ref(null);
const elSagittal = ref(null);
const elCoronal = ref(null);
const elVR = ref(null);

const cornerText = reactive({
	[ViewportId.AXIAL]: {
		name: "Axial",
		desc: "Axial",
		wwwc: "",
		slice: "",
		thickness: "",
		orient: {
			top: "",
			bottom: "",
			left: "",
			right: ""
		}
	},
	[ViewportId.SAGITTAL]: {
		name: "Sagittal",
		desc: "Sagittal",
		wwwc: "",
		slice: "",
		thickness: "",
		orient: {
			top: "",
			bottom: "",
			left: "",
			right: ""
		}
	},
	[ViewportId.CORONAL]: {
		name: "Coronal",
		desc: "Coronal",
		wwwc: "",
		slice: "",
		thickness: "",
		orient: {
			top: "",
			bottom: "",
			left: "",
			right: ""
		}
	}
});

const axialText = computed(() => {
	return cornerText[ViewportId.AXIAL];
});
const sagittalText = computed(() => {
	return cornerText[ViewportId.SAGITTAL];
});

const coronalText = computed(() => {
	return cornerText[ViewportId.CORONAL];
});

const axialStyle = computed(() => {
	if (layout.maxViewId === ViewportId.AXIAL) {
		return {
			gridRowStart: 1,
			gridRowEnd: 3,
			gridColumnStart: 1,
			gridColumnEnd: 3
		};
	} else {
		if (layout.type === "layoutmpr") {
			return {
				gridRowStart: 1,
				gridRowEnd: 3,
				gridColumnStart: 2,
				gridColumnEnd: 3
			};
		} else if (layout.type === "layoutmprvr") {
			return {
				gridRowStart: 1,
				gridRowEnd: 2,
				gridColumnStart: 1,
				gridColumnEnd: 2
			};
		}
	}
});

const vrStyle = computed(() => {
	if (layout.maxViewId === ViewportId.VOLUME) {
		return {
			gridRowStart: 1,
			gridRowEnd: 3,
			gridColumnStart: 1,
			gridColumnEnd: 3
		};
	} else {
		if (layout.type === "layoutmpr") {
			return {
				gridRowStart: 2,
				gridRowEnd: 3,
				gridColumnStart: 2,
				gridColumnEnd: 3
			};
		} else if (layout.type === "layoutmprvr") {
			return {
				gridRowStart: 1,
				gridRowEnd: 2,
				gridColumnStart: 2,
				gridColumnEnd: 3
			};
		}
	}
});

const sagittalStyle = computed(() => {
	if (layout.maxViewId === ViewportId.SAGITTAL) {
		return {
			gridRowStart: 1,
			gridRowEnd: 3,
			gridColumnStart: 1,
			gridColumnEnd: 3
		};
	} else {
		if (layout.type == "layoutmpr") {
			return {
				gridRowStart: 1,
				gridRowEnd: 2,
				gridColumnStart: 1,
				gridColumnEnd: 2
			};
		} else if (layout.type == "layoutmprvr") {
			return {
				gridRowStart: 2,
				gridRowEnd: 3,
				gridColumnStart: 1,
				gridColumnEnd: 2
			};
		}
	}
});

const coronalStyle = computed(() => {
	if (layout.maxViewId === ViewportId.CORONAL) {
		return {
			gridRowStart: 1,
			gridRowEnd: 3,
			gridColumnStart: 1,
			gridColumnEnd: 3
		};
	} else {
		if (layout.type == "layoutmpr") {
			return {
				gridRowStart: 2,
				gridRowEnd: 3,
				gridColumnStart: 1,
				gridColumnEnd: 2
			};
		} else if (layout.type == "layoutmprvr") {
			return {
				gridRowStart: 2,
				gridRowEnd: 3,
				gridColumnStart: 2,
				gridColumnEnd: 3
			};
		}
	}
});

watch(
	() => layout.type,
	(newVal, oldVal) => {
		// let viewIds = [];
		// let maxViewId = null;
		layout.viewIds.length = 0;
		if (newVal === "layoutmpr") {
			showAxial.value = true;
			showSagittal.value = true;
			showCoronal.value = true;
			showVR.value = false;
		} else if (newVal === "layoutmprvr") {
			showAxial.value = true;
			showSagittal.value = true;
			showCoronal.value = true;
			showVR.value = true;
		}

		if (showAxial.value) {
			layout.viewIds.push(ViewportId.AXIAL);
		}
		if (showSagittal.value) {
			layout.viewIds.push(ViewportId.SAGITTAL);
		}
		if (showCoronal.value) {
			layout.viewIds.push(ViewportId.CORONAL);
		}
		if (showVR.value) {
			layout.viewIds.push(ViewportId.VOLUME);
		}

		resizeViews();

		// const resizeTimer = setTimeout(() => {
		// 	theMPR.resize(viewIds, maxViewId);
		// 	clearTimeout(resizeTimer);
		// }, 100);
	}
);

watch(
	() => layout.maxViewId,
	(newVal, oldVal) => {
		// console.log("layout.maxViewId", newVal, oldVal);
		showAxial.value = newVal === null || newVal === ViewportId.AXIAL;
		showSagittal.value = newVal === null || newVal === ViewportId.SAGITTAL;
		showCoronal.value = newVal === null || newVal === ViewportId.CORONAL;
		showVR.value = newVal === null || newVal === ViewportId.VOLUME;

		layout.viewIds.length = 0;
		if (showAxial.value) {
			layout.viewIds.push(ViewportId.AXIAL);
		}
		if (showSagittal.value) {
			layout.viewIds.push(ViewportId.SAGITTAL);
		}
		if (showCoronal.value) {
			layout.viewIds.push(ViewportId.CORONAL);
		}
		if (showVR.value) {
			layout.viewIds.push(ViewportId.VOLUME);
		}
		resizeViews();
	}
);

// watch(measureType, (newVal, oldVal) => {
// 	theMPR.setMeasureType(newVal);
// });

const setMeasureType = type => {
	theMPR.setMeasureType(type);
};

const repeat = (n, s) => {
	let dst = "";
	for (let i = 0; i < n; i++) {
		dst += s + " ";
	}
	return dst;
};

const setLayout = type => {
	layout.type = type;
};

const drawText = () => {
	console.log("drawText");
};

const renderHandler = e => {
	updateText(e);
};

const cameraHandler = e => {
	udpateOrientation(e);
};

const getViewportName = viewportId => {};

const updateText = e => {
	const { viewportId } = e.detail;
	const wwwl = theMPR.getWindow(viewportId);
	if (!wwwl) return;
	// console.log("updateText", viewportId, wwwl);
	const text = `WL: ${wwwl.windowCenter} WW: ${wwwl.windowWidth}`;
	const sliceCount = theMPR.getSliceCount(viewportId);
	const sliceIdx = theMPR.getSliceIndex(viewportId);
	const sliceText = `Im: ${sliceIdx + 1} / ${sliceCount}`;
	const thickness = theMPR.getSlabThickness(viewportId).toFixed(2);
	if (thickness > 0.1) {
		cornerText[
			viewportId
		].desc = `${cornerText[viewportId].name} ${blendMode.value} Thickness: ${thickness} mm`;
	} else {
		cornerText[viewportId].desc = cornerText[viewportId].name;
	}

	// console.log("thickness", viewportId, thickness);

	cornerText[viewportId].wwwc = text;
	cornerText[viewportId].slice = sliceText;
};

const udpateOrientation = e => {
	// console.log("udpateOrientation element", e.detail);
	const { viewportId, camera, rotation, previousCamera } = e.detail;
	const markers = theMPR.getOrientationMarkers({ camera, rotation });
	if (markers && showOrientText.value) {
		cornerText[viewportId].orient = markers;
	}
	// console.log("markers", markers);

	if (appStore.syncOperation.syncZoom) {
		if (viewportId === currentViewportId.value) {
			theMPR.syncZoom(viewportId, camera, previousCamera);
		}
	}
};

const setBlendMode = mode => {
	theMPR.setBlendMode(mode);
};

const setVRColor = preset => {
	theMPR.setVRColor(preset);
};

const setWindow = (ww, wl) => {
	theMPR.setWindow(ww, wl);
};

const setDefaultWindow = () => {
	// console.log("setDefaultWindow");
	theMPR.setWindow(defWW.value, defWL.value);
};

const getCurWindow = () => {
	const wwwl = theMPR.getWindow(ViewportId.AXIAL);
	return {
		ww: wwwl.windowWidth,
		wl: wwwl.windowCenter
	};
};

const removeTools = () => {
	theMPR.removeAnnotations();
};

const onSelectView = e => {
	// console.log("OnSelectView", e);
	const elem = e.target.closest(".sliceview");
	if (!elem) {
		return;
	}
	currentViewportId.value = elem.getAttribute("data-viewport-uid");
	// console.log("elem", elem, currentViewportId.value);
};

const onDbClick = e => {
	// console.log(e.currentTarget.id + " dbclick.");
	layout.maxViewId = layout.maxViewId === null ? e.currentTarget.id : null;
	console.log("maxView:" + layout.maxViewId);
};

const toggleCrossline = () => {
	theMPR.toggleCrosshairs();
};

const reset = () => {
	theMPR.resetCamera();
	setDefaultWindow();
};

const setCameraPos = position => {
	theMPR.setCameraPosition(position);
};

// const resize = () => {
// 	const resizeTimer = setTimeout(() => {
// 		theMPR.resize(viewIds, maxViewId);
// 		clearTimeout(resizeTimer);
// 	}, 100);
// };

const load = async () => {
	const imageIds = currentDisplayer.value.getImageIds();

	loading.value = true;
	// const firstImg = imageIds(0);
	const info = await getDicomInfo(imageIds[0]);

	studyInfo.value = info.studyInfo;
	defWL.value = info.defWL;
	defWW.value = info.defWW;

	theMPR.loadImages(imageIds).then(() => {
		loading.value = false;

		// const layout = config.threed.layout || "layoutmpr";
		// this.$bus.$emit("setlayout3d", layout);
		theMPR.enableSyncWindow();
	});
};

const resizeViews = () => {
	const resizeTimer = setTimeout(() => {
		theMPR.resize(layout.viewIds, layout.maxViewId);
		reset();
		clearTimeout(resizeTimer);
	}, 100);
};

const showOutline = show => {
	theMPR.showOutline(show);
};

const showAxes = show => {
	theMPR.showAxes(show);
};

const toggleOrientText = () => {
	showOrientText.value = !showOrientText.value;
};

const changeAxesType = type => {
	theMPR.setAxesType(type);
};

const shiftVRColor = pos => {
	theMPR.shiftVRColor(pos);
};

const enableVRShiftColor = enable => {
	theMPR.enableVolumeShiftColor(enable);
};

defineExpose({
	setLayout,
	setWindow,
	setDefaultWindow,
	setVRColor,
	showOutline,
	showAxes,
	reset,
	toggleOrientText,
	toggleCrossline,
	setMeasureType,
	changeAxesType,
	shiftVRColor,
	enableVRShiftColor,
	setBlendMode,
	setCameraPos
});

onMounted(() => {
	console.log("DisplayArea3D mounted:");

	theMPR = new MPR({
		elAxial: elAxial.value,
		elSagittal: elSagittal.value,
		elCoronal: elCoronal.value,
		elVR: elVR.value
	});

	load();
	theMPR.bindRenderEvent(renderHandler);
	theMPR.bindCameraEvent(cameraHandler);

	resizeObserver = new ResizeObserver(() => {
		resizeViews();
	});
	resizeObserver.observe(elContainer.value);
});

onUnmounted(() => {
	if (resizeObserver) {
		resizeObserver.disconnect();
	}
});

onBeforeUnmount(() => {
	console.log("DisplayArea3DNew beforeUnmount");
	theMPR.destroy();
	theMPR = null;
});
</script>

<style lang="scss" scoped>
$font-size: 14px;
@mixin text() {
	position: absolute;
	color: white;
	font-size: $font-size;
	font-family: Arial, Helvetica, sans-serif;
	text-align: left;
	z-index: 10;
}

@mixin orient($text-align: left) {
	position: absolute;
	color: white;
	font-size: $font-size;
	text-align: $text-align;
	z-index: 10;
}

.container3d {
	display: grid;
	grid-template-columns: 1fr 1fr;
	grid-template-rows: 1fr 1fr;
	grid-gap: 1px 1px;
	height: 100%;
	background-color: black;
	color: #fff;
}

:deep(.el-loading-spinner) {
	font-size: 80px;
	font-weight: bold;
}

:deep(.el-loading-mask .el-loading-spinner .el-loading-text) {
	font-size: 20px;
}

.desc {
	@include text();
	top: 2px;
	left: 2px;
}

.text_studyinfo {
	@include text();
	top: 24px;
	left: 2px;
}

.text_wwwc {
	@include text();
	top: 2px;
	right: 2px;
}

.text_slice {
	@include text();
	top: 24px;
	right: 2px;
}

.orient_top {
	@include orient(center);
	top: 2px;
	left: calc(50% - 30px);
	width: 60px;
}

.orient_bottom {
	@include orient(center);
	bottom: 2px;
	left: calc(50% - 30px);
	width: 60px;
}

.orient_left {
	@include orient();
	top: calc(50% - 20px);
	left: 2px;
}

.orient_right {
	@include orient();
	top: calc(50% - 20px);
	right: 2px;
}

.axialparent {
	/* position: absolute; */
	padding: 1px;
	border: 1px solid rgb(135, 206, 250);
	background-color: black;
}

.sagittalparent {
	/* position: absolute; */
	padding: 1px;
	border: 1px solid red;
	background-color: black;
}

.coronalparent {
	/* position: absolute; */
	padding: 1px;
	border: 1px solid green;
	background-color: black;
}

.vrcprparent {
	/* position: absolute; */
	padding: 1px;
	border: 1px solid white;
	background-color: black;
}

.sliceview {
	position: relative;
	width: 100%;
	height: 100%;
}

.vr-camera {
	position: absolute;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 1px;
	width: 40px;
	right: 0px;
	// height: 197px;
	// background-color: rgba(25, 245, 5, 0.5);
	z-index: 10;
}

canvas {
	width: 100%;
	height: 100%;
}
</style>
